package com.hex.ds.hdrs.common.utils;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hex.ds.hdrs.common.constant.ErrorCode;
import com.hex.ds.hdrs.common.exception.BizException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lwz
 * @date 2020-12-03
 * @des
 */
public class HttpUtils {

    /**
     *
     */
    public static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    /**
     * 请求默认编码
     */
    private static final String CHARSET = "UTF-8";

    /**
     * contextType application/json 类型
     */
    private static final String APPLICATION_JSON = "application/json";

    /**
     * contextType text/json 类型
     */
    private static final String CONTEXT_TYPE_TEXT_JSON = "text/json";


    /**
     * httpGet按照默认编码请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @return
     */
    public static String httpGet(String url, Map<String, Object> paramsMap) throws Exception{
        return httpGet(url, paramsMap, CHARSET);
    }

    /**
     * httpGet按照默认编码请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @param localFileName 本地文件名，带路径
     * @return
     */
    public static boolean httpDownFile(String url, Map<String, Object> paramsMap,String localFileName) {
        return httpPostDownFile(url, paramsMap, CHARSET, localFileName);

        //return httpDownFile(url, paramsMap, CHARSET, localFileName);
    }

    /**
     * httpGet请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @param charset   请求编码
     * @return
     */
    public static boolean httpDownFile(String url, Map<String, Object> paramsMap, String charset,String localFileName) {
        HttpClient client = HttpClientBuilder.create().build();
        String result = "";
        HttpResponse resp = null;
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs = getRequestPair(paramsMap);
        try {
            if (!CollectionUtils.isEmpty(pairs)) {
                url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
            }
            logger.info(url);
            HttpGet httpGet = new HttpGet(url);
            httpGet.addHeader(HTTP.CONTENT_TYPE, CONTEXT_TYPE_TEXT_JSON);
            httpGet.addHeader("fileName",paramsMap.get("fileName").toString());
            resp = client.execute(httpGet);
            int code = resp.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity respEntity = resp.getEntity();
                if(respEntity!=null){
                    //返回数据
                    FileUtils.copyInputStreamToFile(respEntity.getContent(), new File(localFileName));
                }
                // result = EntityUtils.toString(respEntity, charset);
                return true;
            } else {
                HttpEntity respEntity = resp.getEntity();
                String result2 =  EntityUtils.toString(respEntity, charset);
                RetBase ret= JSON.parseObject(result2,RetBase.class);
                if(ret.getErrCode().equals(ErrorCode.ERROR_4000997.getCode())){
                    throw new BizException(ErrorCode.ERROR_4000997.getCode(), ErrorCode.ERROR_4000997.getMessage()+":" + code);
                }else {
                    throw new BizException(ErrorCode.ERROR_300002, "http调用失败，返回httpCode:" + code);
                }
            }
        } catch (Exception e) {
            if (e instanceof BizException) {
                throw new BizException(((BizException) e).getCode(), ((BizException) e).getErrMsg());
            }
            else{
                throw new BizException(ErrorCode.ERROR_300002,e.getMessage());
            }
        }

    }
    /**
     * httpGet请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @param charset   请求编码
     * @return
     */
    public static boolean httpPostDownFile(String url, Map<String, Object> paramsMap, String charset,String localFileName) {
        HttpClient client = HttpClientBuilder.create().build();
        String result = "";
        HttpResponse resp = null;
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs = getRequestPair(paramsMap);
        try {
            if (!CollectionUtils.isEmpty(pairs)) {
                url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
            }
            logger.info(url);
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader(HTTP.CONTENT_TYPE, CONTEXT_TYPE_TEXT_JSON);
            resp = client.execute(httpPost);
            int code = resp.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity respEntity = resp.getEntity();
                if(respEntity!=null){
                    //返回数据
                    FileUtils.copyInputStreamToFile(respEntity.getContent(), new File(localFileName));
                }
                // result = EntityUtils.toString(respEntity, charset);
                return true;
            } else {
                HttpEntity respEntity = resp.getEntity();
                String result2 =  EntityUtils.toString(respEntity, charset);
                RetBase ret= JSON.parseObject(result2,RetBase.class);
                if(ret.getErrCode().equals(ErrorCode.ERROR_4000997.getCode())){
                    throw new BizException(ErrorCode.ERROR_4000997.getCode(), ErrorCode.ERROR_4000997.getMessage()+":" + code);
                }else {
                    throw new BizException(ErrorCode.ERROR_300002, "http调用失败，返回httpCode:" + code);
                }
            }
        } catch (Exception e) {
            if (e instanceof BizException) {
                throw new BizException(((BizException) e).getCode(), ((BizException) e).getErrMsg());
            }
            else{
                throw new BizException(ErrorCode.ERROR_300002,e.getMessage());
            }
        }

    }
    /**
     * httpPost按照默认编码请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @return
     */
    public static String httpPost(String url, Map<String, Object> paramsMap) {
        return httpPost(url, paramsMap, CHARSET);
    }

    /**
     * 按照默认编码请求-httpJsonPost
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @return
     */
    public static String httpJsonPost(String url, Map<String, Object> paramsMap) {
        return httpJsonPost(url, JSONUtil.toJsonStr(paramsMap), CHARSET);
    }

    /**
     * 按照默认编码请求-httpJsonPost
     *
     * @param url  请求URL
     * @param json 请求参数
     * @return
     */
    public static String httpJsonPost(String url, String json) {
        return httpJsonPost(url, json, CHARSET);
    }
    /**
     * 按照默认编码请求-httpJsonPost
     *
     * @param url  请求URL
     * @param paramObject 请求参数
     * @return
     */
    public static String httpJsonPost(String url, Object paramObject) {
        return httpJsonPost(url, JSONUtil.toJsonStr(paramObject), CHARSET);
    }

    /**
     * httpGet请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @param charset   请求编码
     * @return
     */
    public static String httpGet(String url, Map<String, Object> paramsMap, String charset) throws Exception{
        HttpClient client = HttpClientBuilder.create().build();
        String result = "";
        HttpResponse resp = null;
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs = getRequestPair(paramsMap);
        try {
            if (!CollectionUtils.isEmpty(pairs)) {
                url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
            }
            HttpGet httpGet = new HttpGet(url);
            RequestConfig requestConfig = RequestConfig.custom()
                    .setConnectTimeout(3000).setConnectionRequestTimeout(1000)
                    .setSocketTimeout(3000).build();
            httpGet.setConfig(requestConfig);


            resp = client.execute(httpGet);
            int code = resp.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity respEntity = resp.getEntity();
                result = EntityUtils.toString(respEntity,charset);
            } else {
                throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败，返回httpCode:" + code);
            }
        } catch (Exception e) {
            throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败:", e);
        }
        return result;
    }

    /**
     * httpGet请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @return
     */
    public static String httpJsonGet(String url, Map<String, Object> paramsMap) {
        return httpJsonGet(url, paramsMap, CHARSET);
    }

    /**
     * httpGet请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @param charset   请求编码
     * @return
     */
    public static String httpJsonGet(String url, Map<String, Object> paramsMap, String charset) {
        HttpClient client = HttpClientBuilder.create().build();
        String result = "";
        HttpResponse resp = null;
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs = getRequestPair(paramsMap);
        try {
            if (!CollectionUtils.isEmpty(pairs)) {
                url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, charset));
            }
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader(HttpHeaders.ACCEPT, APPLICATION_JSON);
            resp = client.execute(httpGet);
            int code = resp.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity respEntity = resp.getEntity();
                result = EntityUtils.toString(respEntity,charset);
            } else {
                throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败，返回httpCode:" + code);
            }
        } catch (Exception e) {
            throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败:", e);
        }
        return result;
    }

    /**
     * httpPost请求
     *
     * @param url       请求URL
     * @param paramsMap 请求参数
     * @param charset   请求编码
     * @return
     */
    public static String httpPost(String url, Map<String, Object> paramsMap, String charset) {
        HttpClient client = HttpClientBuilder.create().build();
        String result = "";
        HttpResponse resp = null;
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        pairs = getRequestPair(paramsMap);
        try {
            HttpPost httpPost = new HttpPost(url);
            if (!CollectionUtils.isEmpty(pairs)) {
                httpPost.setEntity(new UrlEncodedFormEntity(pairs, charset));
            }
            resp = client.execute(httpPost);
            int code = resp.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity respEntity = resp.getEntity();
                result = EntityUtils.toString(respEntity,charset);
            } else {
                throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败，返回httpCode:" + code);
            }
        } catch (Exception e) {
            throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败:", e);
        }
        return result;
    }


    /**
     * httpJsonPost请求
     *
     * @param url      请求URL
     * @param jsonBody 请求参数
     * @param charset  请求编码
     * @return
     */
    public static String  httpJsonPost(String url, String jsonBody, String charset) {
        HttpClient client = HttpClientBuilder.create().build();
        String result = "";
        HttpResponse resp = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
            if (!StringUtils.isEmpty(jsonBody)) {
                StringEntity entity = new StringEntity(jsonBody, charset);
                entity.setContentType(CONTEXT_TYPE_TEXT_JSON);
                entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));
                httpPost.setEntity(entity);
            }
            resp = client.execute(httpPost);
            int code = resp.getStatusLine().getStatusCode();
            if (code == HttpStatus.SC_OK) {
                HttpEntity respEntity = resp.getEntity();
                result = EntityUtils.toString(respEntity,charset);
            } else {
                HttpEntity respEntity = resp.getEntity();
                String result2 = EntityUtils.toString(respEntity,charset);
                logger.debug(result2);
                throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败，返回httpCode:" + code);
            }
        } catch (Exception e) {
            throw new BizException(ErrorCode.ERROR_300002.getCode(), "http调用失败:", e);
        }
        return result;
    }

    /**
     * 根据Map获取参数List
     *
     * @param paramsMap
     * @return
     */
    private static List<NameValuePair> getRequestPair(Map<String, Object> paramsMap) {
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        if (null != paramsMap && !paramsMap.isEmpty()) {
            for (String key : paramsMap.keySet()) {
                pairs.add(new BasicNameValuePair(key, paramsMap.get(key).toString()));
            }
        }
        return pairs;
    }

    /**
     * 获取请求IP
     * @param request
     * @return
     */
    public static String getRequestIP(HttpServletRequest request){
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<>();
        map.put("fileName","aa.zip");
        HttpUtils.httpDownFile("http://localhost:8004/agent/downAgentLog",map,"utf-8","D:/tangji/aa.zip");
    }
}
